unit DUnitX.StringUtils;
interface
uses SBD.Generics;

type
IStringEnumerable = interface( ISEnumerable<string>)
  ['{12EB292B-9B33-4088-B523-826BF289E44A}']
  end;

IStringCursor = interface( ISEnumerator<string>)
  ['{0C0D1CFD-FBC6-4376-A09C-D4083C2CDBBA}']
  end;

function Split( const Joined, Delimiter : string): IStringEnumerable;

implementation



type
TSplitter = class( TSEnumerable<string>, IStringEnumerable)
  private
    FJoined: string;
    FDelimiter: string;

  private type
    TParticleCursor = class ( TSEnumerator<string>)
      private
        FBuffer: string;
        FCrsrDelim: string;
        FDelimLen: integer;
        function DelimPos: integer;
      protected
        function MoveNext: boolean;                              override;
        function GetCurrent: string;                             override;
      public
        constructor Create( Enumerable1: TSEnumerable<string>);  override;
      end;

  protected
    function GetEnumerator: ISEnumerator<string>;                override;
  public
    constructor Create( const Joined, Delimiter : string);
  end;


function Split( const Joined, Delimiter : string): IStringEnumerable;
begin
result := TSplitter.Create( Joined, Delimiter)
end;


constructor TSplitter.Create( const Joined, Delimiter: string);
begin
FJoined    := Joined;
FDelimiter := Delimiter
end;

constructor TSplitter.TParticleCursor.Create( Enumerable1: TSEnumerable<string>);
begin
inherited Create( Enumerable1);
with Enumerable1 as TSplitter do
  begin
  FCrsrDelim := FDelimiter;
  FBuffer    := FCrsrDelim + FJoined
  end;
FDelimLen  := Length( FCrsrDelim)
end;

function TSplitter.TParticleCursor.DelimPos: integer;
begin
result := Pos( FCrsrDelim, FBuffer)
end;

function TSplitter.TParticleCursor.GetCurrent: string;
var
  P: integer;
begin
result := FBuffer;
P := DelimPos;
if P > 0 then
  SetLength( result, P - 1)
end;

function TSplitter.TParticleCursor.MoveNext: boolean;
var
  P: integer;
begin
P := DelimPos;
result := P > 0;
if not result then exit;
Delete( FBuffer, 1, P + FDelimLen - 1)
end;

function TSplitter.GetEnumerator: ISEnumerator<string>;
begin
result := TSplitter.TParticleCursor.Create( self)
end;

end.
